<script setup>
import {ref, onMounted} from "vue";
import {useRoute, useRouter} from "vue-router";
import MonacoEditor from "@guolao/vue-monaco-editor";
import {Base64} from "js-base64";
import {getScriptDetail, addScript, updateScript, runScript} from '@/api/script'

const route = useRoute();
const router = useRouter();

const code = ref("");
const language = ref("java");
const output = ref("");
const isRunning = ref(false);
const isDragging = ref(false);
const rightPanelWidth = ref(400);
const startX = ref(0);
const startWidth = ref(0);
const isDarkTheme = ref(false);
const scriptName = ref("");
const id = ref(null);

const javaTemplate = `package expand.example;
public class Test {
    public static String execute() {
        return "Hello, world!";
    }
}`;

const jsTemplate = `// 一个简单的 Hello World 示例
console.log("Hello, World!");

// 返回一个值
return "Hello from JavaScript!";`;

const insertTemplate = () => {
  language.value = "java";
  code.value = javaTemplate;
};

const insertJsTemplate = () => {
  language.value = "javascript";
  code.value = jsTemplate;
};

const handleCodeChange = (value) => {
  code.value = value;
};

const handleLanguageChange = (e) => {
  language.value = e.target.value;
  code.value = "";
};

const handleSave = async () => {
  const base64Code = Base64.encode(code.value);

  if (!scriptName.value) {
    alert("请输入脚本名称");
    return;
  }

  try {
    const data = {
      code: base64Code,
      name: scriptName.value,
      language: language.value
    }

    if (!id.value) {
      await addScript(data)
    } else {
      await updateScript({...data, id: id.value})
    }
    alert('保存成功')
  } catch (error) {
    console.error("保存失败:", error)
    alert('保存失败: ' + error.message)
  }
};

const runCode = async () => {
  isRunning.value = true;
  output.value = "";

  try {
    if (language.value === "java") {
      try {
        const base64Code = Base64.encode(code.value);
        const res = await runScript({code: base64Code, id: id.value, name: scriptName.value})
        output.value = JSON.stringify(res.data, null, 2)
      } catch (error) {
        output.value = "错误: " + error.message
      }
      return;
    }

    const originalLog = console.log;
    console.log = (...args) => {
      output.value += args.join(" ") + "\n";
      originalLog.apply(console, args);
    };

    const result = new Function(code.value)();

    if (result !== undefined) {
      output.value += "返回值: " + result + "\n";
    }

    console.log = originalLog;
  } catch (error) {
    output.value = "错误: " + error.message;
  } finally {
    isRunning.value = false;
  }
};

const handleMouseDown = (e) => {
  isDragging.value = true;
  startX.value = e.clientX;
  startWidth.value = rightPanelWidth.value;
  document.addEventListener("mousemove", handleMouseMove);
  document.addEventListener("mouseup", handleMouseUp);
  document.body.style.userSelect = "none";
};

const handleMouseMove = (e) => {
  if (!isDragging.value) return;
  const newWidth = Math.max(
      200,
      Math.min(
          window.innerWidth - 400,
          startWidth.value - (e.clientX - startX.value)
      )
  );
  rightPanelWidth.value = newWidth;
};

const handleMouseUp = () => {
  isDragging.value = false;
  document.removeEventListener("mousemove", handleMouseMove);
  document.removeEventListener("mouseup", handleMouseUp);
  document.body.style.userSelect = "";
};

const toggleTheme = () => {
  isDarkTheme.value = !isDarkTheme.value;
};

const fetchScript = async (scriptId) => {
  try {
    const res = await getScriptDetail(scriptId)
    const scriptData = res.data
    code.value = Base64.decode(scriptData.code)
    language.value = scriptData.language.toLowerCase()
    scriptName.value = scriptData.name || ""
    id.value = scriptData.id || null
  } catch (error) {
    console.error("获取脚本详情失败:", error);
  }
};

onMounted(() => {
  const scriptId = route.params.id;
  if (scriptId) {
    fetchScript(Number(scriptId));
  }
});
</script>

<template>
  <div class="main-container" :class="{ 'light-theme': !isDarkTheme }">
    <div
        class="code-editor-container"
        :style="{ right: `${rightPanelWidth}px` }"
    >
      <div class="editor-title">
        <h1>在线代码编辑器</h1>
      </div>
      <div class="script-name-container">
        <input
            type="text"
            v-model="scriptName"
            placeholder="请输入脚本名称..."
            class="script-name-input"
        />
      </div>
      <div class="editor-header">
        <div class="left-controls">
          <select
              v-model="language"
              @change="handleLanguageChange"
              class="language-select"
          >
            <option value="javascript">JavaScript</option>
            <option value="java">Java</option>
          </select>
          <button
              @click="toggleTheme"
              class="theme-button"
              :title="isDarkTheme ? '切换到亮色主题' : '切换到暗色主题'"
          >
            <span class="icon">{{ isDarkTheme ? "🌞" : "🌙" }}</span>
          </button>
        </div>
        <div class="button-group">
          <button @click="insertTemplate" class="template-button">
            <span class="icon">📝</span>
            Java模板
          </button>
          <button @click="insertJsTemplate" class="template-button js-template">
            <span class="icon">📝</span>
            JS模板
          </button>
          <button @click="handleSave" class="save-button">
            <span class="icon">💾</span>
            保存代码
          </button>
          <button @click="runCode" class="run-button" :disabled="isRunning">
            <span class="icon">▶️</span>
            运行代码
          </button>
        </div>
      </div>

      <MonacoEditor
          v-model:value="code"
          :language="language"
          :theme="isDarkTheme ? 'vs-dark' : 'vs'"
          :options="{
          minimap: { enabled: true },
          fontSize: 18,
          lineNumbers: 'on',
          scrollBeyondLastLine: false,
          automaticLayout: true,
          padding: { top: 20 },
        }"
          class="editor-main"
          @change="handleCodeChange"
      />
    </div>

    <div
        class="resizer"
        @mousedown="handleMouseDown"
        :class="{ 'is-dragging': isDragging }"
        :style="{ right: `${rightPanelWidth}px` }"
    ></div>

    <div class="output-container" :style="{ width: `${rightPanelWidth}px` }">
      <div class="output-title">
        <h2>运行结果</h2>
      </div>
      <div
          class="output-content"
          :class="{ 'has-error': String(output).includes('错误:') }"
      >
        {{ output || "运行代码后将在此显示结果..." }}
      </div>
    </div>
  </div>
</template>

<style scoped>
.main-container {
  display: flex;
  width: 100%;
  height: 100vh;
  background-color: #1e1e1e;
  position: relative;
  overflow: hidden;
}

.main-container.light-theme {
  background-color: #ffffff;
}

.light-theme .code-editor-container {
  background-color: #ffffff;
  color: #000;
}

.light-theme .editor-title h1 {
  color: #000;
}

.light-theme .language-select {
  background: #f5f5f5;
  color: #000;
  border-color: #ddd;
}

.light-theme .language-select option {
  background: #ffffff;
  color: #000;
}

.light-theme .editor-main {
  border-color: #ddd;
}

.light-theme .output-container {
  background-color: #ffffff;
  color: #000;
}

.light-theme .output-title h2 {
  color: #000;
}

.light-theme .output-content {
  background-color: #f5f5f5;
  color: #067a3a;
}

.light-theme .output-content.has-error {
  color: #d32f2f;
}

.light-theme .resizer {
  background-color: #ddd;
}

.light-theme .resizer:hover,
.light-theme .resizer.is-dragging {
  background-color: #999;
}

.left-controls {
  display: flex;
  gap: 10px;
  align-items: center;
}

.theme-button {
  padding: 6px 12px;
  background: transparent;
  border: 1px solid #404040;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.3s ease;
}

.light-theme .theme-button {
  border-color: #ddd;
}

.theme-button:hover {
  background-color: rgba(255, 255, 255, 0.1);
}

.light-theme .theme-button:hover {
  background-color: rgba(0, 0, 0, 0.1);
}

.code-editor-container {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  right: 400px;
  display: flex;
  flex-direction: column;
  padding: 24px;
  background-color: #1e1e1e;
  color: #fff;
}

.editor-title {
  margin-bottom: 20px;
}

.editor-title h1 {
  font-size: 24px;
  font-weight: 500;
  color: #fff;
  margin: 0;
}

.editor-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.language-select {
  padding: 6px 12px;
  border: 1px solid #404040;
  border-radius: 4px;
  background: #2d2d2d;
  color: #fff;
  font-size: 14px;
  min-width: 120px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.language-select:hover {
  border-color: #666;
}

.language-select option {
  background: #2d2d2d;
  color: #fff;
}

.editor-main {
  flex: 1;
  border: 1px solid #404040;
  border-radius: 8px;
  overflow: hidden;
}

.save-button {
  padding: 8px 20px;
  background-color: #2d5af2;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 8px;
  transition: all 0.3s ease;
}

.save-button:hover {
  background-color: #4070ff;
  transform: translateY(-1px);
}

.save-button:active {
  transform: translateY(0);
}

.icon {
  font-size: 16px;
}

.button-group {
  display: flex;
  gap: 10px;
}

.run-button {
  padding: 8px 20px;
  background-color: #2ea043;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 8px;
  transition: all 0.3s ease;
}

.run-button:hover {
  background-color: #3fb950;
  transform: translateY(-1px);
}

.run-button:active {
  transform: translateY(0);
}

.run-button:disabled {
  background-color: #2ea04380;
  cursor: not-allowed;
  transform: none;
}

.output-container {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  background-color: #1e1e1e;
  color: #fff;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.output-title {
  margin-bottom: 20px;
}

.output-title h2 {
  font-size: 20px;
  font-weight: 500;
  color: #fff;
  margin: 0;
}

.output-content {
  flex: 1;
  background-color: #2d2d2d;
  border-radius: 8px;
  padding: 16px;
  font-family: "Consolas", "Monaco", monospace;
  font-size: 14px;
  white-space: pre-wrap;
  overflow-y: auto;
  color: #a9dc76;
}

.output-content.has-error {
  color: #ff6188;
}

.template-button {
  padding: 8px 20px;
  background-color: #7e57c2;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 8px;
  transition: all 0.3s ease;
}

.template-button:hover {
  background-color: #9575cd;
  transform: translateY(-1px);
}

.template-button:active {
  transform: translateY(0);
}

.resizer {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 4px;
  background-color: #404040;
  cursor: col-resize;
  z-index: 100;
}

.resizer:hover,
.resizer.is-dragging {
  background-color: #666;
}

.resizer::after {
  content: "";
  position: absolute;
  left: -4px;
  right: -4px;
  top: 0;
  bottom: 0;
  cursor: col-resize;
  z-index: 101;
}

@media (max-width: 640px) {
  .code-editor-container {
    position: relative;
    right: 0 !important;
    padding: 16px;
  }

  .editor-title h1 {
    font-size: 20px;
  }

  .editor-header {
    flex-direction: column;
    gap: 10px;
  }

  .language-select,
  .save-button {
    width: 100%;
  }

  .main-container {
    flex-direction: column;
  }

  .output-container {
    position: relative;
    width: 100% !important;
    height: 300px;
  }

  .button-group {
    flex-direction: column;
    width: 100%;
  }

  .template-button,
  .save-button,
  .run-button {
    width: 100%;
  }

  .resizer {
    display: none;
  }

  .left-controls {
    width: 100%;
  }

  .theme-button {
    flex: 0 0 auto;
  }
}

.template-button.js-template {
  background-color: #f7df1e; /* JavaScript 标志色 */
  color: #000;
}

.template-button.js-template:hover {
  background-color: #f7df1e99;
}

.script-name-container {
  margin-bottom: 16px;
}

.script-name-input {
  width: 100%;
  padding: 8px 12px;
  font-size: 16px;
  border: 1px solid #404040;
  border-radius: 4px;
  background: #2d2d2d;
  color: #fff;
  transition: all 0.3s ease;
}

.script-name-input:focus {
  outline: none;
  border-color: #2d5af2;
}

.light-theme .script-name-input {
  background: #f5f5f5;
  border-color: #ddd;
  color: #000;
}

.light-theme .script-name-input:focus {
  border-color: #2d5af2;
}
</style>
